﻿package shooter
{
	import flash.events.KeyboardEvent;
	import flash.ui.Keyboard;
	import render3d.interfaces.IRender3DAdapter;

	public class CameraController 
	{
		static public const DEFAULT_ROTATION:int = -90; // degrees
		static public const CAMERA_HEIGHT:int = 100;
		// Mouse looking and moving
		private const MOUSE_SENSITIVITY:Number = 0.5;
		private const LOOKGATE:Number = 1000;	
		private const MAXIMUM_X_ROTATION:int = 55;
		private const DISTANCE:Number = 20;
		private const JUMP_SPEED:Number = 20;
		
		private var lastMouseX:Number;
		private var lastMouseY:Number;
		private var mouseLook:Boolean = false;
		private var jumpSpeed:Number = 0;
		
		// Key's states
		public var isForward:Boolean = false;
		public var isBack:Boolean = false;
		public var isLeft:Boolean = false;
		public var isRight:Boolean = false;
		public var isRun:Boolean = false;
		public var isJump:Boolean = false;
				
		private var gridX:Number;
		private var gridY:Number;
		
		private var level:Level;
		private var render:IRender3DAdapter;
		
		public function CameraController(render:IRender3DAdapter, level:Level)
		{
			this.render = render;
			this.level = level;
		}
		
		/** set position */
		public function setPosition(x:int, y:int):void
		{
			this.gridX = x/level.tileSize;
			this.gridY = y/level.tileSize;
			render.setCameraPosition(x, y, CAMERA_HEIGHT);
		}
		
		//--------------------------------------------------------------------------
		//
		//  Listeners 
		//
		//--------------------------------------------------------------------------
		
		public function update(stageMouseX:Number, stageMouseY:Number):void
		{
			var cameraPanAngle:Number = render.getCameraPanAngle();
			var cameraHeight:Number = render.getCameraHeight();
			
			// Mouse Looking
			if (mouseLook) {
				var movementMouseX:Number = (stageMouseX - lastMouseX)*MOUSE_SENSITIVITY;
				var movementMouseY:Number = (stageMouseY - lastMouseY)*MOUSE_SENSITIVITY;
				render.lookCamera(movementMouseX, movementMouseY);
				lastMouseX = stageMouseX;
				lastMouseY = stageMouseY;
			}
			
			// Jumping		
			if (cameraHeight > CAMERA_HEIGHT) jumpSpeed -= 1/level.tileSize;
			else jumpSpeed = 0;
			if (isJump && cameraHeight == CAMERA_HEIGHT) jumpSpeed = JUMP_SPEED/level.tileSize
			
			// Moving
			var runMultiplier:Number = 1
			if (isRun) runMultiplier = 2;
			
			var dist:Number = DISTANCE/level.tileSize * runMultiplier;
			
			var forwardSpeed:Number = 0;
			var rightSpeed:Number = 0;
			if (isForward) {
				rightSpeed = dist * Math.sin(-cameraPanAngle);
				forwardSpeed = dist * Math.cos(-cameraPanAngle);
			}else if (isBack) {
				rightSpeed = -dist * Math.sin(-cameraPanAngle);
				forwardSpeed = -dist * Math.cos(-cameraPanAngle);
			}else if (isLeft) {
				rightSpeed = -dist * Math.cos(-cameraPanAngle);
				forwardSpeed = dist * Math.sin(-cameraPanAngle);
			}else if (isRight) {
				rightSpeed = dist * Math.cos(-cameraPanAngle);
				forwardSpeed = -dist * Math.sin(-cameraPanAngle);
			}
				
			// check Collisions
			rightSpeed = level.checkCollisionX(gridX, gridY, rightSpeed);
			forwardSpeed = level.checkCollisionY(gridX, gridY, forwardSpeed)
			
			// render
		
			render.moveCamera(forwardSpeed * level.tileSize, rightSpeed * level.tileSize, jumpSpeed * level.tileSize)
			
			// add speed to Cell coordinates
			this.gridX += rightSpeed;
			this.gridY += forwardSpeed;
		}
		
		public function onMouse(isMouseDown:Boolean, stageMouseX:Number, stageMouseY:Number):void
		{
			if(isMouseDown){
				mouseLook = true;
				lastMouseX = stageMouseX;
				lastMouseY = stageMouseY;
			}else {
				mouseLook = false;
			}
		}

		public function onKey(e:KeyboardEvent):void
		{
			var isKeyDown:Boolean = e.type == KeyboardEvent.KEY_DOWN;
			switch(e.keyCode){
				case Keyboard.UP: case 87: isForward = isKeyDown; break; // W
				case Keyboard.LEFT: case 65: isLeft = isKeyDown; break; // A
				case Keyboard.DOWN: case 83: isBack = isKeyDown; break; // S
				case Keyboard.RIGHT: case 68: isRight = isKeyDown; break; // D
				case Keyboard.SHIFT: isRun = isKeyDown; break;
				case Keyboard.SPACE: isJump = isKeyDown; break;
			}
		}
	}
}